#include <string.h>
#include "script.h"
#include "script_block.h"
#include "script_func.h"
#include "script_include.h"
#include "TFly_list.h"
#include "script_debug.h"
#include "script_memory.h"
#include "script_stack.h"
#include "script_string.h"
#include "script_var.h"

static  TFly_list_t *g_includes = NULL;

script_include_t *script_include_create(char *name)
{
	script_include_t *inc = NULL;
	if(g_includes){
		TFly_list_item_t item = {0};
		while(1){
			inc = TFly_list_item_get(g_includes,&item);
			if(inc == NULL){
				break;
			}
			if(strcmp(inc->name,name) == 0){
				inc->refer++;
				//printf("\033[32m%s %d inc:%s %p\033[0m\r\n",__func__,__LINE__,name,inc->script);
				//show_exp_var(inc->script->exec_block->vars,0);
				//printf("\033[32m%s %d inc:%s\033[0m\r\n",__func__,__LINE__,name);
				return inc;
			}
		}
	}

	inc = script_calloc(1,sizeof(script_include_t));
	if(inc == NULL){
		SCRIPT_DEBUG_ERR("calloc fail!");
		return NULL;
	}
	inc->name = script_string_dump(name);
	if(g_includes == NULL){
		g_includes = TFly_list_create();
	}
	TFly_list_add(g_includes,inc);

	script_t *script = script_load(name);
	if(script == NULL){
		SCRIPT_DEBUG_ERR("include script load fail!");
		return NULL;
	}

	inc->script = script;
	inc->refer++;

	//run_script(script);

	//printf("\033[32m%s %d inc:%s %p %p\033[0m\r\n",__func__,__LINE__,inc->name,inc,inc->script);
	//show_exp_var(inc->script->exec_block->vars,0);
	return inc;
}

int script_include_destroy(script_include_t *inc)
{
	if(inc == NULL){
		return 0;
	}
	
	if(inc->refer > 1){
		inc->refer--;
		return 0;
	}

	TFly_list_del(g_includes,inc);
	if(inc->name){
		script_free(inc->name);
	}
	script_destroy(inc->script);
	script_free(inc);

	return 0;
}

void script_include_uninit(void)
{
	if(g_includes == NULL){
		return;
	}

	script_include_t *inc = TFly_list_del_first(g_includes);
	while(inc){
		script_include_destroy(inc);
		inc = TFly_list_del_first(g_includes);
	}
	
	TFly_list_destroy(g_includes);
}

include_data_t *script_include_data_generate(script_include_t *inc,script_exec_block_t *env)
{
	include_data_t *data = script_calloc(1,sizeof(*data));
	data->inc = inc;
	data->block = script_exec_block_create(inc->script->main_code);

	exp_var_copy(inc->script->exec_block->vars,data->block->vars);

	TFly_list_item_t item = {0};
	exp_var_t *tmp = TFly_list_item_get(&data->block->vars->object->children,&item);
	while(tmp){
		if(tmp->type == EXP_VAR_TYPE_FUNCTION &&
				tmp->func->func->type == EXEC_FUNC_TYPE_SCRIPT){
			tmp->func->block = data->block;
		}
		tmp = TFly_list_item_get(&data->block->vars->object->children,&item);
	}

	memset(&item,0,sizeof(item));
	exp_var_t *cfunc = TFly_list_item_get(&env->vars->object->children,&item);
	while(cfunc){
		//cfunc = exp_var_point_take(cfunc);
		if(cfunc->type == EXP_VAR_TYPE_FUNCTION &&
				cfunc->func->func->type == EXEC_FUNC_TYPE_C){
			//exp_var_t *v = exp_var_create(cfunc->name);
			//v->type = EXP_VAR_TYPE_POINT;
			//v->var = exp_var_refer(cfunc);
			//exp_var_struct_add(data->block->vars,v);
			exp_var_struct_add(data->block->vars,exp_var_refer(cfunc));
		}

		cfunc = TFly_list_item_get(&env->vars->object->children,&item);
	}


	script_stack_t *stack = script_stack_create(1);
	script_stack_Push(stack,data->block);
	exp_node_t *result = _run_block(data->block,stack);
	exp_node_destroy(result);
	script_stack_Pop(stack);
	script_stack_destroy(stack);

	//printf("\033[33m%s %d\033[0m\r\n",__func__,__LINE__);
	//show_exp_var(data->block->vars,0);
	//printf("\033[33m%s %d\033[0m\r\n",__func__,__LINE__);

	return data;
}

include_data_t *script_include_get(script_t *script, char *include_name)
{
	if(script == NULL || include_name == NULL){
		return NULL;
	}
	TFly_list_item_t item = {0};

	include_data_t *data = TFly_list_item_get(script->includes,&item);
	while(data){
		if(data->var_name != NULL && strcmp(include_name,data->var_name) == 0){
			return data;
		}
		data = TFly_list_item_get(script->includes,&item);
	}
	return NULL;
}
